package db;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

/**
 * This is a wrapper for really basic actions with a MySQL database. As it is,
 * it enables selects.
 *
 * Last Modified: Aug 24, 2010<br>
 * Version: 1.0<br>
 * Created: Jul 15, 2010<br>
 * Author: Katie Kuksenok (katie.kuksenok@gmail.com)
 *
 * @author Katie
 */
public class ConnectionManager {

    private Connection conn = null;

    /**
     * Convenience method that creates a new Manager, giving it parameters to instantiate a Connection to a running MySQL server
     * @param Host - host name
     * @param Schema - default schema
     * @param User - user name
     * @param Pass - password
     */
    public ConnectionManager(String dbHost, String dbSchema, String dbUser, String dbPass) {
        String connString = "jdbc:mysql://" + dbHost + "/" + dbSchema + "?user=" + dbUser + "&password=" + dbPass;
        try {
            DriverManager.setLoginTimeout(1);
            conn = DriverManager.getConnection(connString);
        } catch (SQLException e) {
                System.out.println("MySQL Connection and Query Manager could not be configured: ");
                System.out.println("\t"+e.getMessage());
        }
    }

    public boolean kill(){
        if(isOk()){
            try {
                conn.close();
                conn = null;
            } catch (SQLException ex) {
                conn = null;
                return false;
            }
            conn = null;
            return true;
        }
        return false;
    }


    /**
     * Check the health of the manager
     * @return true iff underlying connector is properly configured
     */
    public boolean isOk() {
        return conn!=null;
    }
    /**
     * Execute a INSERT, UPDATE, or DELETE statement and return the resulting ResultSet.
     * @param ps - prepared statement for the select
     * @return null if the connection is ill, or if something went wrong.
     * A description of the runtime exception will be given in the case of the latter.
     */
    public boolean update(PreparedStatement ps){
        if(!isOk())
            return false;
        try{
            ps.executeUpdate();
            return true;
        }
        catch(SQLException e){
            return false;
        }
    }

    /**
     * Execute a SELECT select and return the resulting ResultSet.
     * @param ps - prepared statement for the select
     * @return null if the connection is ill, or if something went wrong.
     * A description of the runtime exception will be given in the case of the latter.
     */
    public ResultSet select(PreparedStatement ps){
        if(!isOk())
            return null;
        try{
            return ps.executeQuery();
        }
        catch(SQLException e){
            return null;
        }
    }

    /**
     * Method enables a message to be displayed, along with a rough estimate of how long it took to execute. Estimate gotten by subtracting System.curTimeMillis after execution from that prior to execution.
     * A convenience method; besides extra output that is useful for logging and debugging, it is equivalent to using select(ps)
     * @param ps
     * @param message - a message to be displayed, such as something indicating where the method was called from or under what conditions.
     * @return
     */
    public ResultSet selectVerbose(PreparedStatement ps, String message){
        long cur = System.currentTimeMillis();
        ResultSet rs = select(ps);
        System.out.println("qSel(PrepSt) "+message+" "+(System.currentTimeMillis()-cur)+" ms");
        return rs;
    }

    /**
     * Method enables a message to be displayed, along with a rough estimate of how long it took to execute. Estimate gotten by subtracting System.curTimeMillis after execution from that prior to execution.
     * A convenience method; besides extra output that is useful for logging and debugging, it is equivalent to using update(ps)
     * @param ps
     * @param message - a message to be displayed, such as something indicating where the method was called from or under what conditions.
     * @return
     */
    public boolean updateVerbose(PreparedStatement ps, String message){
        long cur = System.currentTimeMillis();
        boolean out = update(ps);
        System.out.println("qUpd(PrepSt) "+message+" "+(System.currentTimeMillis()-cur)+" ms");
        return out;
    }

    public PreparedStatement getPS(String query){
        try{
            return conn.prepareStatement(query);
        }catch(Exception e){
            return null;
        }
    }

}
